/**
 * 用户管理路由
 *
 * Created by snowingsea on 2020/01/22.
 */
const middleware = require('./../middleware');
const users = require('./../../models/users');
const publisher = require('./../../models/redis/publisher');
const PhoenixError = require('./../../models/phoenix-error');
const utility = require('./../../models/utility');

/**
 * 获取用户信息
 * @param req
 * @param res
 * @param next
 */
function getUser(req, res, next) { // eslint-disable-line no-unused-vars
  res.json(users.getJson(req.$user));
}

/**
 * 批量获取用户列表
 * @param req
 * @param res
 * @param next
 */
function getUsers(req, res, next) {
  const resUsers = {
    pagination: req.filter,
  };
  users.getUserList({
    ...req.query,
    page: parseInt(req.query.page, 10) || 1,
    pageSize: parseInt(req.query.perPage, 10) || 10,
  })
    .then(({ total, users: list }) => {
      resUsers.users = list.map((user) => users.getJson(user));
      resUsers.pagination.total = total;
      res.json(resUsers);
    })
    .catch((err) => {
      next(new PhoenixError(err));
    });
}

/**
 * 获取用户分组信息
 * @param req
 * @param res
 * @param next
 */
function getUserGroup(req, res, next) {
  const resGroup = {
    total: 0,
    status: [],
    roles: [],
  };
  users.getGroupCount('status')
    .then((data) => {
      const countMap = new Map();
      data.forEach(({ _id, count }) => {
        resGroup.total += count;
        countMap.set(_id, count);
      });
      Object.keys(users.statusKind).forEach((key) => {
        const status = users.statusKind[key];
        resGroup.status.push({
          status,
          name: key,
          count: countMap.has(status) ? countMap.get(status) : 0,
        });
      });
      return users.getGroupCount('role');
    })
    .then((data) => {
      Object.keys(users.roleKind).forEach((key) => {
        const role = users.roleKind[key];
        let roleCount = 0;
        data.forEach(({ _id, count }) => {
          if ((_id & role) > 0) { // eslint-disable-line no-bitwise
            roleCount += count;
          }
        });
        resGroup.roles.push({
          role,
          name: key,
          count: roleCount,
        });
      });
      res.json(resGroup);
    })
    .catch((err) => {
      next(new PhoenixError(err));
    });
}

/**
 * 系统管理员添加用户
 * @param req
 * @param res
 * @param next
 */
function addUser(req, res, next) {
  const {
    username,
    password,
    roles,
    nickname,
    lang,
  } = req.body;
  let err;
  if (!username || !password || !roles) {
    err = new PhoenixError('invalid request',
      'Missing parameters. "username", "password" and "roles" are required');
  } else if (roles) {
    (utility.isArrayType(roles) ? roles : [roles]).forEach((role) => {
      role = Number.parseInt(role.toString(), 10);
      if ((users.roleKind.superUser & role) > 0) { // eslint-disable-line no-bitwise
        err = new PhoenixError('over range', 'Can not add a superuser');
      }
    });
  }
  if (err) {
    next(err);
    return;
  }

  Promise.resolve()
    .then(() => users.addUser(username, password, roles, nickname, lang))
    .then((user) => {
      res.json(users.getJson(user));
    })
    .catch((err) => {
      if (err.code === 11000) {
        err = new PhoenixError('conflict', 'user already exist');
      }
      next(new PhoenixError(err));
    });
}

/**
 * 删除用户
 * @param req
 * @param res
 * @param next
 */
function removeUser(req, res, next) {
  if ((req.$user.role & users.roleKind.superUser) > 0) { // eslint-disable-line no-bitwise
    next(new PhoenixError('over range', 'Can not remove a superuser'));
    return;
  }

  users.removeUser(req.params.userId)
    .then(() => {
      res.status(204).json();
    })
    .catch((err) => {
      next(new PhoenixError(err));
    });
}

/**
 * 批量删除用户
 * @param req
 * @param res
 * @param next
 */
function removeUsers(req, res, next) {
  users.getUsers(req.query, users.getUserOptions(req.query))
    .then((resUsers) => {
      const promises = resUsers.map(({ _id }) => users.removeUser(_id));
      return Promise.all(promises);
    })
    .then(() => {
      res.status(204).json();
    })
    .catch((err) => {
      next(new PhoenixError(err));
    });
}

/**
 * 编辑用户信息
 * @param req
 * @param res
 * @param next
 */
function updateUser(req, res, next) {
  const { userId } = req.params;
  if (req.query.password) { req.query.password = null; }
  if (req.body.password) { req.query.password = req.body.password; }

  const { roles } = req.query;
  let err;
  if (roles) {
    (utility.isArrayType(roles) ? roles : [roles]).forEach((role) => {
      role = Number.parseInt(role.toString(), 10);
      if ((users.roleKind.superUser & role) > 0) { // eslint-disable-line no-bitwise
        err = new PhoenixError('over range', 'Can not change role to a superuser');
      }
    });
  }
  if (err) {
    next(err);
    return;
  }

  Promise.resolve()
    .then(() => users.updateUser(userId, req.query))
    .then(() => {
      if (req.query.status) {
        switch (Number.parseInt(req.query.status.toString(), 10)) {
          case users.statusKind.offline:
            publisher.publishLogoutMessage(userId);
            break;
          default:
            break;
        }
      }
      if (req.query.password) {
        publisher.publishLogoutMessage(userId);
      }
      return users.getUser(userId);
    })
    .then((user) => {
      res.json(users.getJson(user));
    })
    .catch((err) => {
      if (err.code === 11000) {
        err = new PhoenixError('conflict', 'username already exist');
      }
      next(new PhoenixError(err));
    });
}

/**
 * Export model definition object.
 */
module.exports = (app, prefix) => {
  const usersURL = `${prefix}/users.json`;
  const userURL = `${prefix}/users/:userId.json`;
  const userGroupURL = `${prefix}/group/users.json`;

  // 获取用户信息
  app.get(userURL, middleware.user.requireTokenUnexpired);
  app.get(userURL, middleware.user.requireAvailable);
  app.get(userURL, middleware.user.requireAdministrator);
  app.get(userURL, middleware.user.requireUserExist);
  app.get(userURL, getUser);

  // 获取用户列表
  app.get(usersURL, middleware.user.requireTokenUnexpired);
  app.get(usersURL, middleware.user.requireAvailable);
  app.get(usersURL, middleware.splitFilter);
  app.get(usersURL, getUsers);

  // 获取用户分组统计
  app.get(userGroupURL, middleware.user.requireTokenUnexpired);
  app.get(userGroupURL, middleware.user.requireAvailable);
  app.get(userGroupURL, middleware.user.requireAdministrator);
  app.get(userGroupURL, getUserGroup);

  // 添加用户
  app.post(usersURL, middleware.user.requireTokenUnexpired);
  app.post(usersURL, middleware.user.requireAvailable);
  app.post(usersURL, middleware.user.requireAdministrator);
  app.post(usersURL, addUser);

  // 删除用户
  app.delete(userURL, middleware.user.requireTokenUnexpired);
  app.delete(userURL, middleware.user.requireAvailable);
  app.delete(userURL, middleware.user.requireAdministrator);
  app.delete(userURL, middleware.user.requireUserExist);
  app.delete(userURL, removeUser);

  // 批量删除用户
  app.delete(usersURL, middleware.user.requireTokenUnexpired);
  app.delete(usersURL, middleware.user.requireAvailable);
  app.delete(usersURL, middleware.user.requireAdministrator);
  app.delete(usersURL, removeUsers);

  // 编辑用户信息
  app.put(userURL, middleware.user.requireTokenUnexpired);
  app.put(userURL, middleware.user.requireAvailable);
  app.put(userURL, middleware.user.requireAdministrator);
  app.put(userURL, middleware.user.requireUserExist);
  app.put(userURL, updateUser);
};
